#include "../utils/Profiler.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <sstream>
namespace Putin{


void PerformanceTimer::start()
{
	QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&mFreq));
	QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&mStart));
}

void PerformanceTimer::end()
{
	QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&mEnd));
}

double PerformanceTimer::get()
{
	return (double) (mEnd - mStart) / (double) mFreq;
}



void Profiler::clear()
{
	for each( std::pair<std::string,PerformanceTimer*> pt in mFuncs)
		delete pt.second;
	mFuncs.clear();
	mRes.clear();
}

void Profiler::start(std::string function)
{
	PerformanceTimer* pt = new PerformanceTimer();
	pt->start();
	mFuncs[function] = pt;
}

void Profiler::stop(std::string function)
{
	PerformanceTimer* pt = mFuncs[function];
	if( pt ) // Given a valid function that is inited by start()
	{
		pt->end();
		double t = pt->get();
		delete pt;
		mFuncs.erase(function);

		Times r;
		if( !(mRes.find(function) == mRes.end() ))
			r = mRes[function];
	
		r.cnt++;
		r.acc += t;
		r.avg = r.acc / r.cnt;
		if( t > r.max ) r.max = t;
		if( t < r.min) r.min  = t;
		mRes[function] = r;
	}
}

std::string Profiler::getReport()
{
	std::stringstream ss;
	ss.setf(std::ios::fixed,std::ios::floatfield);
	ss.precision(6);

	for each( std::pair<std::string,Times> tp in mRes)
	{
		Times r = tp.second;
		ss << tp.first << ": " <<
			" samples: " << r.cnt <<
			" avg: " << r.avg <<
			" min: " << r.min <<
			" max: " << r.max << std::endl;
	}
	return ss.str();
}

} // End Namespace 